package Client;

import java.io.*;
import java.net.*;
import java.util.*;

import Requete.RequeteAjoutPersonne;
import Requete.RequeteAjoutSurnomAPersonne;
import Requete.RequeteListerSurnomDunePersonne;
import Requete.RequeteListerToutesPersonnes;
import Requete.RequeteModifierPersonne;
import Requete.RequeteQuitter;
import Requete.RequeteSupprimerPersonne;
import Requete.RequeteSupprimerSurnomDunePersonne;
import util.*;

/**
 * la classe d'un client pour le serveur de surnom
 * 
 * @author Graoudi Nohri & Ochi Ghazi
 * 
 */
public class Client {
    private Socket soc;
    private ObjectInputStream in;
    private ObjectOutputStream out;

    /**
     * 
     * @param nomServer
     *            le serveur de surnom
     * @param port
     *            le port
     */
    public Client(String nomServer, int port) throws UnknownHostException,
            IOException {
        soc = new Socket(nomServer, port);
    }
    
    /**
     * fonction qui lance la boucle qui demande � l'utilisateur ce qu'il d�sire
     * faire
     */
    public void launch() {
        String commande;
        String nom;

        try {
            in = new ObjectInputStream(soc.getInputStream());
        } catch (IOException e) {
            System.out.println("Erreur overture Socket en lecture");
            return;
        }
        try {
            out = new ObjectOutputStream(soc.getOutputStream());
        } catch (IOException e) {
            System.out.println("Erreur ouverture Socket en �criture");
            return;
        }
        
        String menu = "";
        menu += "Bienvenue sur le serveur Polytech'Surnom\n";
        
        String help = "Voici la liste des services sur ce serveur\n";
        help += "GET surnom\n";
        help += "GETLIST\n";
        help += "ADDUSER nom surnom\n";
        help += "ADD surnom1 [surnom]\n";
        help += "DELUSER nom surnom\n";
        help += "DEL surnom\n";
        help += "CHANGE nom surnom nouveauNom\n";
        help += "EXIT\n";
        help += "Pour plus d'informations sur un service tapez MAN NOM où NOM est le nom du service\nExemple :\tMAN GET";
        
        System.out.println(menu);
        System.out.println(help);
        System.out
                .print("Vous pouvez à n'importe quel moment retrouver cette aide en tapant HELP\n");

        for (;;) {

            System.out.print(">>>");
            Scanner sc = new Scanner(System.in);
            while (true)
                try {
                    commande = sc.nextLine();
                    break;
                } catch (InputMismatchException e) {
                    sc = new Scanner(System.in);
                    System.out
                            .println("Tapez une commande ou HELP pour le menu d'aide");
                    System.out.print(">>>");
                }
                
            	String[] lexemes = commande.split(" "); 
                
                if (lexemes[0].equals("GET")) {
                	if(lexemes.length == 3){
                		listerSurnomDunePersonne(lexemes[1],lexemes[2]);
                	}else
                		System.out.println("Erreur 02: Nombre d'arguments");
                }
                
                else if (commande.equals("GETLIST")) {
                	if(lexemes.length == 1){
                    listerToutesPesonnes();
                	}else
                		System.out.println("Erreur 02: Nombre d'arguments");
                }
                
                else if (lexemes[0].equals("ADDUSER")) {
                    if(lexemes.length == 3){                        
                    	ajoutPersonne(lexemes[1],lexemes[2]);
                    }else
                    	System.out.println("Erreur 02: Nombre d'arguments");
                }
                
                else if (lexemes[0].equals("ADD")) {
                    if(lexemes.length == 4){
                    	ajoutSurnomAPersonne(lexemes[1],lexemes[2],lexemes[3]);
                    }else
                    	System.out.println("Erreur 02: Nombre d'arguments");
                }
                
                else if (lexemes[0].equals("DELUSER")) {
                    if(lexemes.length == 3){
                    	supprimerPersonne(lexemes[1],lexemes[2]);
                    }else
                    	System.out.println("Erreur 02: Nombre d'arguments");
                }
                else if (lexemes[0].equals("DEL")) {
                	if(lexemes.length == 3){
                		try {
							supprimerSurnomPersonne(lexemes[1],lexemes[2]);
						} catch (ClassNotFoundException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
                	}else
                    	System.out.println("Erreur 02: Nombre d'arguments");
                }
                
                else if (lexemes[0].equals("CHANGE")) {
                    if(lexemes.length == 4){
                    	modifierPersonne(lexemes[1],lexemes[2],lexemes[3]);
                    }else
                    	System.out.println("Erreur 02: Nombre d'arguments");
                }
                
                else if (lexemes[0].equals("EXIT")) {
                    if(lexemes.length == 1){
                    	System.out.println("=== Deconnection du server ===");
                    	quitter(); 
                    	return;}
                    else{
                    	System.out.println("Erreur 02: Nombre d'arguments");
                    }
                }
                
                else{
                	System.out.println("Erreur 01: Fonction inexistante");
                }
            
        }
    }

    /**
     * fonction appel� lorsque l'on d�sire se d�connecter du server
     */
    private void quitter() {
        try {
            out.writeObject(new RequeteQuitter());
        } catch (IOException e) {
            System.out.println("Erreur Impossible d'envoyer la Requete : "
                    + e.getMessage());
            return;
        }
        try {
            out.close();
            in.close();
            soc.close();
        } catch (IOException e) {
            System.out.println("Imposssible de fermer la socket :"
                    + e.getMessage());
        }
    }

    /**
     * fonction appelé lorsque l'on désire avoir toutes les personnes de la base
     */
    @SuppressWarnings("unchecked")
    private void listerToutesPesonnes() {
        System.out.println("=== Lister toute les personnes ===");
        try {
            out.writeObject(new RequeteListerToutesPersonnes());
        } catch (IOException e) {
            System.out.println("Erreur Impossible d'envoyer la Requete : "
                    + e.getMessage());
            return;
        }

        try {
            ArrayList<Personne> p = (ArrayList<Personne>) in.readObject();
            System.out.println("Nombre de personnes : " + p.size() + "\n");
            for (int i = 0; i < p.size(); ++i) {
                System.out.println(p.get(i));
                System.out.println("=============================");
            }
            System.out.println("OK");
        } catch (ClassNotFoundException e) {
            System.out
                    .println("Erreur Impossible de convertir l'objet recu en "
                            + " ArrayList<Personne>) : " + e.getMessage());
            return;
        } catch (IOException e) {
            System.out.println("Erreur Impossible d'envoyer la Requete : "
                    + e.getMessage());
            return;
        }

    }

    /**
     * fonction appel� lorsque l'on d�sire ajouter un surnom � une personne
     */
    private void ajoutSurnomAPersonne(String nom,String surnom,String surnom2) {
        System.out.println("=== Ajouter un surnom a une personne ===");
        Personne p = creerPersonne(nom,surnom);
        try {
            out.writeObject(new RequeteAjoutSurnomAPersonne(p, surnom2));
        } catch (IOException e) {
            System.out.println("Erreur Impossible d'envoyer la Requete : "
                    + e.getMessage());
            return;
        }
        try {
            try {
				System.out.println((String) in.readObject());
			} catch (ClassNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
        } catch (IOException e) {
            System.out.println("Erreur Impossible de lire la Reponse : "
                    + e.getMessage());
            e.printStackTrace();
        }

    }

    /**
     * fonction appelé lorsque l'on désire modifier une personne
     */
    private void modifierPersonne(String nom,String surnom, String nouveauNom) {
        System.out.println("=== Modifier les informations d'une personne ===");
        Personne old = creerPersonne(nom,surnom);
        Personne _new = creerPersonne(nouveauNom,surnom);
        try {
            out.writeObject(new RequeteModifierPersonne(old, _new));
        } catch (IOException e) {
            System.out.println("Erreur Impossible d'envoyer la Requete : "
                    + e.getMessage());
            return;
        }
        try {
            System.out.println((in.readBoolean() ? "OK" : "Erreur 04 : Cette personne n'existe pas"));
        } catch (IOException e) {
            System.out.println("Erreur Impossible de lire la Reponse : "
                    + e.getMessage());
        }

    }

    /**
     * fonction appelé lorsque l'on désire supprimer une personne
     */
    private void supprimerPersonne(String nom, String surnom) {
        System.out.println("=== Supprimer personne ===");
        Personne p = creerPersonne(nom,surnom);
        try {
            out.writeObject(new RequeteSupprimerPersonne(p));
        } catch (IOException e) {
            System.out.println("Erreur Impossible d'envoyer la Requete : "
                    + e.getMessage());
            return;
        }
        try {
            System.out.println((in.readBoolean() ? "OK" : "Erreur 04 : Cette personne n'existe pas"));
        } catch (IOException e) {
            System.out.println("Erreur Impossible de lire la Reponse : "
                    + e.getMessage());
        }

    }

    /**
     * fonction appelé lorsque l'on désire ajouter une personne
     */
    private void ajoutPersonne(String nom, String surnom) {
    	System.out.println("=== Ajouter une personne ===");
        try {
        	ArrayList<String> surnoms = new ArrayList<String>();
        	surnoms.add(surnom);
            out.writeObject(new RequeteAjoutPersonne(new Etudiant(nom, surnoms)));
            out.flush();
        } catch (IOException e) {
            System.out.println("Erreur Impossible d'envoyer la Requete : "
                    + e.getMessage());
            return;
        }
        try {
            try {
				System.out.println((String)in.readObject());
			} catch (ClassNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
        } catch (IOException e) {
            System.out.println("Erreur Impossible de lire la Reponse : "
                    + e.getMessage());
            e.printStackTrace();
        }
    }

    /**
     * fonction appel� lorsque l'on d�sire lister les surnoms d'une personne
     * @param lexemes 
     */
    @SuppressWarnings("unchecked")
    private void listerSurnomDunePersonne(String nom,String surnom) {
        System.out.println("=== Lister les surnoms d'une personne ===");
        try {
            out
                    .writeObject(new RequeteListerSurnomDunePersonne(
                            creerPersonne(nom,surnom)));
            out.flush();
        } catch (IOException e) {
            System.out.println("Erreur Impossible d'envoyer la Requete : "
                    + e.getMessage());
            return;
        }
        ArrayList<String> a;
        try {
            a = (ArrayList<String>) in.readObject();
            String erreur = "Erreur 04 : Cette personne n'existe pas";
            String erreur2 = "Erreur 03 : La base de données est vide";
            if(a.size()==1 && a.get(0).equals(erreur)){
            	System.out.println(erreur);
            	return;
            }else if(a.size()==1 && a.get(0).equals(erreur2)){
            	System.out.println(erreur);
            	return;
            }
            else{
            for (int i = 0; i < a.size(); ++i) {
                System.out.println((i + 1) + "- " + a.get(i));
            }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

    }
    /**
     * fonction appel� lorsque l'on d�sire supprimer le surnom d'une personne
     *  
     */
    private void supprimerSurnomPersonne(String nom, String surnom) throws ClassNotFoundException {
        System.out.println("=== Supprimer le surnom d'une personne ===");
        Personne p = creerPersonne(nom,surnom);
        try {
            out.writeObject(new RequeteSupprimerSurnomDunePersonne(p, surnom));
        } catch (IOException e) {
            System.out.println("Erreur Impossible d'envoyer la Requete : "
                    + e.getMessage());
            return;
        }
        try {
            Integer a = (Integer) in.readObject();
            switch(a){
            case 10 : 
            	System.out.println("OK");
            	break;
            case 4:
            	System.out.println("Erreur 04 : Cette personne n'existe pas");
            	break;
            default:
            	System.out.println("Erreur 07 : Impossible de supprimer le surnom");
            	break;
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
			e.printStackTrace();
		}

    }

    
    /**
     * fonction qui demande � l'utilisateur de rentrer les informations
     * (nom,prenom et age) d'une personne
     * 
     * @return la personne concern�e
     */
    static public Personne creerPersonne(String nom, String surnom) {
        Personne pers = null;
        ArrayList<String> surnoms = new ArrayList<String>();
        surnoms.add(surnom);
        pers = new Etudiant(nom, surnoms);
        return pers;
    }

}
